package com.yanfan.zutai.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.yanfan.common.annotation.Log;
import com.yanfan.common.core.controller.BaseController;
import com.yanfan.common.core.domain.AjaxResult;
import com.yanfan.common.core.redis.RedisCache;
import com.yanfan.common.core.text.Convert;
import com.yanfan.common.enums.BusinessType;
import com.yanfan.common.utils.poi.ExcelUtil;
import com.yanfan.mqtt.manager.MqttRemoteManager;
import com.yanfan.mqtt.model.PushMessageBo;
import com.yanfan.zutai.aop.SysInitData;
import com.yanfan.zutai.aop.SysInitUpdateData;
import com.yanfan.zutai.aop.SysQueryData;
import com.yanfan.zutai.domain.BDeviceComConfig;
import com.yanfan.zutai.domain.BDeviceDataTestVo;
import com.yanfan.zutai.domain.BDeviceDrive;
import com.yanfan.zutai.domain.BDeviceRealData;
import com.yanfan.zutai.domain.vo.*;
import com.yanfan.zutai.service.*;
import com.yanfan.zutai.util.Detect;
import com.yanfan.zutai.util.EntityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 设备实时数据Controller
 *
 * @author ruoyi
 * @date 2022-05-27
 */
@RestController
@RequestMapping("/zutai/bDeviceRealData")
public class BDeviceRealDataController extends BaseController {
    @Autowired
    private IBDeviceRealDataService bDeviceRealDataService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private IBDeviceManagerService bDeviceManagerService;
    @Autowired
    private IBDeviceComConfigService bDeviceComConfigService;
    @Autowired
    private IBDeviceDriveService bDeviceDriveService;
    @Autowired
    private IBDeviceJsService bDeviceJsService;
    @Autowired
    private RedisCache redisCache;
    @Resource
    private MqttRemoteManager remoteManager;
/**
 * 查询设备实时数据列表
 */
//    @GetMapping("/list")
//    //@SysQueryData
//    public TableDataInfo list(BDeviceRealData bDeviceRealData)
//    {
//        startPage();
//        List<String> imeiList=new ArrayList<>();
//        if(Detect.notEmpty(bDeviceRealData.getZtGuid())){
//            String ztSql="select * from b_device_zt_bind where zt_guid=?";
//            BeanPropertyRowMapper<BDeviceZtBind> bindBeanPropertyRowMapper = new BeanPropertyRowMapper<>(BDeviceZtBind.class);
//            List<BDeviceZtBind> ztBinds = jdbcTemplate.query(ztSql, bindBeanPropertyRowMapper,bDeviceRealData.getZtGuid());
//            for (int i = 0; i <ztBinds.size() ; i++) {
//                imeiList.add(ztBinds.get(i).getDeviceMac());
//            }
//            bDeviceRealData.setImeiList(imeiList);
//        }
//        List<BDeviceRealData> list = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealData);
//        if(bDeviceRealData.getIsQueryParam()){
//            for (int i = 0; i <list.size() ; i++) {
//                BDeviceRealData realData = list.get(i);
//                BDeviceParameter bDeviceParam=new BDeviceParameter();
//                bDeviceParam.setRealDataGuid(realData.getDeviceImei()+"-"+realData.getParamField());
//                List<BDeviceParameter> bDeviceParameters=new ArrayList<>();
//                bDeviceParameters = bDeviceParameterService.selectBDeviceParameterList(bDeviceParam);
//                realData.setParameterList(bDeviceParameters);
//            }
//        }
//        return getDataTable(list);
//    }

    /**
     * 导出设备实时数据列表
     */
    @Log(title = "设备实时数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @SysQueryData
    public void export(HttpServletResponse response, BDeviceRealData bDeviceRealData) {
        List<BDeviceRealData> list = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealData);
        ExcelUtil<BDeviceRealData> util = new ExcelUtil<BDeviceRealData>(BDeviceRealData.class);
        util.exportExcel(response, list, "变量管理");
    }

    /**
     * 获取设备实时数据详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(bDeviceRealDataService.selectBDeviceRealDataById(id));
    }

    /**
     * 新增设备实时数据
     */
    @Log(title = "设备实时数据", businessType = BusinessType.INSERT)
    @PostMapping
    @SysInitData
    public AjaxResult add(@RequestBody BDeviceRealData bDeviceRealData) {
        Integer count = jdbcTemplate.queryForObject("select count(1) from b_device_real_data where device_imei=? and  param_name=?", Integer.class, bDeviceRealData.getDeviceImei(), bDeviceRealData.getParamName());
        if (count > 0) {
            return AjaxResult.error("该名称已存在，请勿重复添加");
        }
        Integer countFiled = jdbcTemplate.queryForObject("select count(1) from b_device_real_data where device_imei=? and  param_field=?", Integer.class, bDeviceRealData.getDeviceImei(), bDeviceRealData.getParamField());
        if (countFiled > 0) {
            return AjaxResult.error("该标识已存在，请勿重复添加");
        }
        Integer code = bDeviceRealDataService.insertBDeviceRealData(bDeviceRealData);
        redisCache.setCacheObject("RealData-" + bDeviceRealData.getDeviceImei() + "-" + bDeviceRealData.getParamField(), bDeviceRealData);
        if (code == 200) {
            return AjaxResult.success("远程设置成功");
        } else {
            return AjaxResult.error("远程设置失败");
        }
    }

    /**
     * 修改设备实时数据
     */
    @Log(title = "设备实时数据", businessType = BusinessType.UPDATE)
    @PutMapping
    @SysInitUpdateData
    public AjaxResult edit(@RequestBody BDeviceRealData bDeviceRealData) {
        Integer count = jdbcTemplate.queryForObject("select count(1) from b_device_real_data where  id !=? and param_name=? and device_imei=?", Integer.class, bDeviceRealData.getId(), bDeviceRealData.getParamName(), bDeviceRealData.getDeviceImei());
        if (count > 0) {
            return AjaxResult.error("该名称已存在，请勿重复修改");
        }
        Integer countFiled = jdbcTemplate.queryForObject("select count(1) from b_device_real_data where id !=? and device_imei=? and  param_field=?", Integer.class, bDeviceRealData.getId(), bDeviceRealData.getDeviceImei(), bDeviceRealData.getParamField());
        if (countFiled > 0) {
            return AjaxResult.error("该标识已存在，请勿重复添加");
        }
        Integer code = bDeviceRealDataService.updateBDeviceRealData(bDeviceRealData);
        redisCache.setCacheObject("RealData-" + bDeviceRealData.getDeviceImei() + "-" + bDeviceRealData.getParamField(), bDeviceRealData);
        if (code == 200) {
            return AjaxResult.success("远程设置成功");
        } else {
            return AjaxResult.error("远程设置失败");
        }
    }

    /**
     * 删除设备实时数据
     */
    @Log(title = "设备实时数据", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        int code = bDeviceRealDataService.deleteBDeviceRealDataByIds(ids);
        return AjaxResult.success("远程删除成功");
    }

    /**
     * 复制实时数据表
     */
    @Log(title = "复制实时数据表", businessType = BusinessType.INSERT)
    @PostMapping(value = "/copyData")
    @SysInitData
    public AjaxResult copyData(@RequestBody BDeviceRealData bDeviceRealData) {
        bDeviceRealData.setId(null);
        bDeviceRealData.setParamName(bDeviceRealData.getParamName() + "_副本");
        bDeviceRealData.setParamValue("");
        bDeviceRealDataService.insertBDeviceRealData(bDeviceRealData);
        return AjaxResult.success();
    }

    /**
     * 查询近两个小时变量曲线图
     */
    @GetMapping("/getVariableLine")
    public AjaxResult getVariableLine(BDeviceRealDataLineVo bDeviceRealData) {
        List<BDeviceRealDataLineVo> variableLine = bDeviceRealDataService.getVariableLine(bDeviceRealData);
        return AjaxResult.success(variableLine);
    }

    /**
     * 查询多个变量统计数据
     */
    @GetMapping("/getVariableLines")
    public AjaxResult getVariableLines(BDeviceRealDataLinesVo bDeviceRealDataLinesVo) {
        BDeviceRealDataLinesVo variableLines = new BDeviceRealDataLinesVo();
        if (Detect.notEmpty(bDeviceRealDataLinesVo.getParamNames())) {
            String[] split = bDeviceRealDataLinesVo.getParamNames().split(";");
            List<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                if (Detect.notEmpty(split[i])) {
                    list.add(split[i]);
                }
            }
            bDeviceRealDataLinesVo.setParamNameList(list);
        }
        if (Detect.notEmpty(bDeviceRealDataLinesVo.getDeviceImei())) {
            String[] split = bDeviceRealDataLinesVo.getDeviceImei().split(";");
            List<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                if (Detect.notEmpty(split[i])) {
                    list.add(split[i]);
                }
            }
            bDeviceRealDataLinesVo.setDeviceImeiList(list);
        }
        if (Detect.notEmpty(bDeviceRealDataLinesVo.getParamFields())) {
            String[] split = bDeviceRealDataLinesVo.getParamFields().split(";");
            List<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                if (Detect.notEmpty(split[i])) {
                    list.add(split[i]);
                }
            }
            bDeviceRealDataLinesVo.setParamFieldList(list);
        }
        if (bDeviceRealDataLinesVo.getParamNameList() == null) {
            return AjaxResult.success(variableLines);
        }
        variableLines = bDeviceRealDataService.getVariableLines(bDeviceRealDataLinesVo);
        return AjaxResult.success(variableLines);
    }
    /**
     * 指令下发
     */
//    @Log(title = "指令下发", businessType = BusinessType.INSERT)
//    @PostMapping(value = "/orderSend")
//    public AjaxResult orderSend(@RequestBody BDeviceRealData bDeviceRealData)
//    {
//        String topic = "/IOT/WULIANYUN/ORDERSEND/" + bDeviceRealData.getDeviceImei();
//        if(Detect.isEmpty(bDeviceRealData.getParamValue())){
//            return AjaxResult.error("变量值为空，无法设置");
//        }
//        BDeviceRealData bDeviceRealDataQuery=new BDeviceRealData();
//        bDeviceRealDataQuery.setDeviceImei(bDeviceRealData.getDeviceImei());
//        bDeviceRealDataQuery.setParamField(bDeviceRealData.getParamField());
//        List<BDeviceRealData> realDataList = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealDataQuery);
//        Object paramValue=bDeviceRealData.getParamValue();
//        String scriptGuid="";
//        if(realDataList.size()>0){
//            BDeviceRealData realData = realDataList.get(0);
//            scriptGuid=realData.getScriptGuid();
//            if(Detect.notEmpty(realData.getWriteFormula())){
//                String exp=realData.getWriteFormula();
//                if(exp.indexOf("A")==-1){
//                    System.out.println("无效的公式");
//                }else{
//                    exp=exp.replace(" ","");
//                    JEP jep = new JEP();
//                    jep.addVariable("A", Convert.toDouble(paramValue));
//                    Node parse = null;
//                    try {
//                        parse = jep.parse(exp);
//                        paramValue = jep.evaluate(parse);
//                        System.out.println("计算后的结果："+paramValue);
//                    } catch (ParseException e) {
//                        System.out.println("公式有误，无法计算");
//                    }
//                }
//            }
//        }
//        bDeviceRealData.setParamValue(Convert.toStr(paramValue));
//        System.out.println("下发的指令参数为："+bDeviceRealData.getParamValue());
//        BDeviceDataTestVo mapping = EntityUtil.mapping(bDeviceRealData, BDeviceDataTestVo.class);
//        String message=JSON.toJSONString(mapping);
//        try {
//            if(Detect.notEmpty(scriptGuid)){
//                ScriptEngineManager factory = new ScriptEngineManager();
//                ScriptEngine engine = factory.getEngineByName ("JavaScript");
//                BDeviceJs bDeviceJs = bDeviceJsService.selectBDeviceJsByGuid(scriptGuid);
//                engine.eval(bDeviceJs.getScriptContent());
//                Invocable inv = (Invocable) engine;
//                Object reportToJson = inv.invokeFunction(bDeviceJs.getFunctionName(), new Object[] {message});
//                message=reportToJson.toString();
//                System.out.println("自定义脚本解析："+message);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            System.out.println("脚步解析错误");
//        }
//        try {
//            // 发送至前端
//             PushMessageBo messageBo = new PushMessageBo();
//             messageBo.setTopic(topic);
//             messageBo.setMessage(JSON.toJSONString(bDeviceWarn));
//             remoteManager.pushCommon(topic, message.getBytes("UTF-8"), 1, false);
//        } catch (UnsupportedEncodingException e) {
//            System.out.println("mqtt消息发送失败，"+e.toString());
//            return AjaxResult.error("mqtt消息发送失败");
//        }
//        //为方便测试。默认生成回复帧
//        bDeviceRealDataService.deviceReplyData(bDeviceRealData.getDeviceImei(),bDeviceRealData.getParamField(),bDeviceRealData.getParamValue());
//        Boolean isSuccess=false;
//        for (int i = 0; i <20 ; i++) {
//            Object key = redisService.getKey("Device-Reply-"+bDeviceRealData.getDeviceImei());
//            if(key!=null){
//                isSuccess=true;
//                break;
//            }
//            try {
//                Thread.sleep(500);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        if(isSuccess){
//            redisService.delKey("Device-Reply-" + bDeviceRealData.getDeviceImei());
//            return AjaxResult.success("指令下发成功");
//        }else{
//            return AjaxResult.error("指令下发失败");
//        }
//    }

    /**
     * 设备excel导入
     */
    @PostMapping("/importData")
    @ResponseBody
    public AjaxResult importData(MultipartFile file, String deviceImei) throws Exception {
        if (Detect.isEmpty(deviceImei)) {
            return AjaxResult.error("参数不符合规定");
        }
        if (file.isEmpty()) {
            return AjaxResult.error("无效的配置文件");
        }
        if (file.getOriginalFilename().indexOf("json") == -1) {
            return AjaxResult.error("无效的配置文件");
        }
        InputStream inputStream = file.getInputStream();
        List<BDeviceRealData> deviceList = new ArrayList<>();
        JSONArray jsonContentList = null;
        try {
            jsonContentList = JSON.parseArray(inputStream);
        } catch (Exception e) {
            return AjaxResult.error("无效的配置文件");
        } finally {
            inputStream.close();
        }
        for (Object jsonObject : jsonContentList) {
            BDeviceRealData bDeviceRealData = JSONObject.parseObject(jsonObject.toString(), BDeviceRealData.class);
            if (Detect.notEmpty(bDeviceRealData.getParamField())) {
                BDeviceRealData bDeviceRealData1 = new BDeviceRealData();
                bDeviceRealData1.setParamField(bDeviceRealData.getParamField());
                bDeviceRealData1.setDeviceImei(deviceImei);
                List<BDeviceRealData> realDatas = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealData1);
                if (realDatas.size() == 0) {
                    bDeviceRealData.setDeviceImei(deviceImei);
                    deviceList.add(bDeviceRealData);
                }
            }
        }
        if (deviceList.size() > 0) {
            String message = bDeviceRealDataService.importData(deviceList);
            return AjaxResult.success(message);
        } else {
            return AjaxResult.error("无效的配置文件");
        }
    }

    /**
     * 数据同步
     */
    @PostMapping("/dataSync")
    @ResponseBody
    public AjaxResult dataSync(@RequestBody BDeviceRealData bDeviceRealData) throws Exception {
        if (Detect.isEmpty(bDeviceRealData.getDeviceImei())) {
            return AjaxResult.error("无效的设备编号，无法同步");
        }
        Boolean isOnline = bDeviceManagerService.selectBDeviceManagerOnlineByImei(bDeviceRealData.getDeviceImei());
        if (!isOnline) {
            return AjaxResult.error("设备不在线，无法同步");
        }
        // 通讯口集合
        BDeviceComConfig bDeviceComConfig = new BDeviceComConfig();
        bDeviceComConfig.setDeviceImei(bDeviceRealData.getDeviceImei());
        List<BDeviceComConfig> bDeviceComConfigs = bDeviceComConfigService.selectBDeviceComConfigList(bDeviceComConfig);
        List<BDeviceSetCom> comConfigList = EntityUtil.mapping(bDeviceComConfigs, BDeviceSetCom.class);
        // 驱动集合
        BDeviceDrive bDeviceDrive = new BDeviceDrive();
        bDeviceDrive.setDeviceImei(bDeviceRealData.getDeviceImei());
        List<BDeviceDrive> bDeviceDrives = bDeviceDriveService.selectBDeviceDriveList(bDeviceDrive);
        List<BDeviceSetDrive> driveList = EntityUtil.mapping(bDeviceDrives, BDeviceSetDrive.class);
        // 变量集合
        List<BDeviceRealData> bDeviceRealDatas = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealData);
        List<BDeviceSetRealData> realDataList = EntityUtil.mapping(bDeviceRealDatas, BDeviceSetRealData.class);

        Map map = new HashMap();
        map.put("comList", comConfigList);
        map.put("driveList", driveList);
        map.put("realDataList", realDataList);
        String topic = "/IOT/WULIANYUN/DATASYNC/" + bDeviceRealData.getDeviceImei();
        // 发送至前端
        PushMessageBo messageBo = new PushMessageBo();
        messageBo.setTopic(topic);
        messageBo.setMessage(JSON.toJSONString(map));
        remoteManager.pushCommon(messageBo);

        // 为方便测试。默认生成回复帧
        bDeviceRealDataService.deviceReplyData(bDeviceRealData.getDeviceImei(), "", "");
        Boolean isSuccess = false;
        for (int i = 0; i < 20; i++) {
            Object key = redisCache.getCacheObject("Device-Reply-" + bDeviceRealData.getDeviceImei());
            if (key != null) {
                isSuccess = true;
                break;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (isSuccess) {
            redisCache.deleteObject("Device-Reply-" + bDeviceRealData.getDeviceImei());
            return AjaxResult.success("数据同步成功");
        } else {
            return AjaxResult.error("数据同步失败");
        }
    }
//    @GetMapping("/getBindDatalist")
//    public TableDataInfo getBindDatalist(BDeviceRealData bDeviceRealData)
//    {
//        startPage();
//        List<BDeviceRealData> list=new ArrayList<>();
//        if(Detect.isEmpty(bDeviceRealData.getZtGuid())){
//            return getDataTable(list);
//        }
//        BDeviceZtBind bDeviceZtBind=new BDeviceZtBind();
//        bDeviceZtBind.setZtGuid(bDeviceRealData.getZtGuid());
//        List<BDeviceZtBind> bindList = bDeviceZtBindService.selectBDeviceZtBindList(bDeviceZtBind);
//        List<String> imeiList=new ArrayList<>();
//        for (int i = 0; i < bindList.size(); i++) {
//            BDeviceZtBind ztBind = bindList.get(i);
//            imeiList.add(ztBind.getDeviceMac());
//        }
//        bDeviceRealData.setImeiList(imeiList);
//        list = bDeviceRealDataService.selectBDeviceRealDataList(bDeviceRealData);
//        return getDataTable(list);
//    }
//    @GetMapping("/getInitData")
//    public AjaxResult getInitData(BDeviceRealData bDeviceRealData)
//    {
//        startPage();
//        List<BDeviceRealData> list=new ArrayList<>();
//        if(Detect.isEmpty(bDeviceRealData.getZtGuid())){
//            return AjaxResult.success();
//        }
//        BDeviceZtBind bDeviceZtBind=new BDeviceZtBind();
//        bDeviceZtBind.setZtGuid(bDeviceRealData.getZtGuid());
//        List<BDeviceZtBind> bindList = bDeviceZtBindService.selectBDeviceZtBindList(bDeviceZtBind);
//        List<String> imeiList=new ArrayList<>();
//        for (int i = 0; i < bindList.size(); i++) {
//            BDeviceZtBind ztBind = bindList.get(i);
//            imeiList.add(ztBind.getDeviceMac());
//        }
//        bDeviceRealData.setImeiList(imeiList);
//        List<Map> mapList=new ArrayList<>();
//        for (int i = 0; i <imeiList.size() ; i++) {
//            BDeviceRealData realData=new BDeviceRealData();
//            realData.setDeviceImei(imeiList.get(i));
//            list = bDeviceRealDataService.selectBDeviceRealDataList(realData);
//            Map<String,String> map=new HashMap<>();
//            for (int j = 0; j <list.size() ; j++) {
//                map.put(list.get(j).getParamField(),list.get(j).getParamValue());
//            }
//            map.put("imei",imeiList.get(i));
//            mapList.add(map);
//        }
//        return AjaxResult.success(mapList);
//    }

    /**
     * 数据调试
     */
    @Log(title = "数据调试", businessType = BusinessType.INSERT)
    @PostMapping(value = "/dataTest")
    public AjaxResult dataTest(@RequestBody BDeviceRealData bDeviceRealData) {
        String topic = "/IOT/WULIANYUN/DATATEST/" + bDeviceRealData.getDeviceImei();
        Boolean aBoolean = bDeviceManagerService.selectBDeviceManagerOnlineByImei(bDeviceRealData.getDeviceImei());
        if (!aBoolean) {
            return AjaxResult.error("设备不在线，无法调试");
        }
        BDeviceDataTestVo mapping = EntityUtil.mapping(bDeviceRealData, BDeviceDataTestVo.class);
        String message = JSON.toJSONString(mapping);
        Boolean isSuccess = false;
        // 发送至前端
        PushMessageBo messageBo = new PushMessageBo();
        messageBo.setTopic(topic);
        messageBo.setMessage(message);
        remoteManager.pushCommon(messageBo);
        // 为方便测试。默认生成回复帧
        bDeviceRealDataService.deviceReplyData(bDeviceRealData.getDeviceImei(), bDeviceRealData.getParamField(), Convert.toStr(RandomUtil.randomInt(0, 100)));
        for (int i = 0; i < 20; i++) {
            Object key = redisCache.getCacheObject("Device-Reply-" + bDeviceRealData.getDeviceImei());
            if (key != null) {
                isSuccess = true;
                break;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (isSuccess) {
            redisCache.deleteObject("Device-Reply-" + bDeviceRealData.getDeviceImei());
            return AjaxResult.success();
        } else {
            return AjaxResult.error();
        }
    }
}
